package com.bf.electroplating.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bf.electroplating.mapper.RainfallOutletMonitoringMapper;
import com.bf.electroplating.pojo.entity.RainfallOutletMonitoring;
import com.bf.electroplating.pojo.entity.RainfallOutletMonitoringLog;
import com.bf.electroplating.pojo.enums.MachineStatusEnums;
import com.bf.electroplating.pojo.enums.ValveStatusEnums;
import com.bf.electroplating.pojo.vo.ResultVO;
import com.bf.electroplating.pojo.vo.rainfallOutletMonitoring.*;
import com.bf.electroplating.pojo.vo.rainfallOutletMonitoring.RainfallOutletMonitoringQueryDTO;
import com.bf.electroplating.pojo.vo.rainfallOutletMonitoring.RainfallOutletMonitoringVO;
import com.bf.electroplating.service.IRainfallOutletMonitoringLogService;
import com.bf.electroplating.service.IRainfallOutletMonitoringService;
import com.bf.electroplating.service.compoent.HJ212Server;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 雨排口监控表 服务实现类
 * </p>
 *
 * @author gzd
 * @since 2025-08-22
 */
@Slf4j
@Service
public class RainfallOutletMonitoringServiceImpl extends ServiceImpl<RainfallOutletMonitoringMapper, RainfallOutletMonitoring> implements IRainfallOutletMonitoringService {

    @Resource
    private IRainfallOutletMonitoringLogService rainfallOutletMonitoringLogService;
    
    @Resource
    private HJ212Server hj212Server;
    
    private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

    @Override
    public ResultVO < Page <RainfallOutletMonitoringVO> > pageList (RainfallOutletMonitoringQueryDTO queryDTO ) {
        Page <RainfallOutletMonitoring> page = new Page <> ( queryDTO.getPageNum () , queryDTO.getPageSize () );

        LambdaQueryWrapper< RainfallOutletMonitoring > wrapper = new LambdaQueryWrapper <> ();

        if ( org.apache.commons.lang3.StringUtils.isNotBlank ( queryDTO.getCompanyId () ) ) {
            wrapper.eq ( RainfallOutletMonitoring::getCompanyId , queryDTO.getCompanyId () );
        }

        if ( StringUtils.isNotBlank ( queryDTO.getMnCode () ) ) {
            wrapper.like ( RainfallOutletMonitoring::getMnCode , queryDTO.getMnCode () );
        }

        if ( !CollectionUtils.isEmpty(queryDTO.getTimes () ) ) {
            wrapper.ge ( RainfallOutletMonitoring::getMonitoringTime , queryDTO.getTimes ().get ( 0 ) )
                    .le(RainfallOutletMonitoring::getMonitoringTime , queryDTO.getTimes ().get ( 1 ) );
        }


        wrapper.orderByDesc ( RainfallOutletMonitoring::getCreateTime );

        Page < RainfallOutletMonitoring > resultPage = this.page ( page , wrapper );

        // 转换为VO
        Page < RainfallOutletMonitoringVO > voPage = new Page <> ();
        BeanUtils.copyProperties ( resultPage , voPage , "records" );
        List< RainfallOutletMonitoringVO > voList = new ArrayList<>();
        for ( RainfallOutletMonitoring entity : resultPage.getRecords () ) {
            RainfallOutletMonitoringVO vo = new RainfallOutletMonitoringVO ();
            BeanUtils.copyProperties ( entity , vo );
            vo.setStatus(MachineStatusEnums.getDesc(vo.getStatus()));
            vo.setMonitoringTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(entity.getMonitoringTime()));
            if (vo.getDeviceName().contains("雨排口")){
                vo.setEmergencyPoolLevel(entity.getRainOutletLevel());
                vo.setEmergencyPoolValveStatus(entity.getRainOutletValveStatus());
            }
            voList.add ( vo );
        }
        voPage.setRecords ( voList );
        return ResultVO.ok ( voPage );
    }





    @Override
    public ResultVO < RainfallOutletMonitoringVO > getDetail (RainfallOutletDetailDTO dto ) {
        if ( StringUtils.isBlank ( dto.getId() ) ) {
            return ResultVO.fail ( "ID不能为空" );
        }
        RainfallOutletMonitoring entity = this.getById ( dto.getId() );
        if ( entity == null ) {
            return ResultVO.fail ( "记录不存在" );
        }
        RainfallOutletMonitoringVO vo = new RainfallOutletMonitoringVO ();
        BeanUtils.copyProperties ( entity , vo );
        Page <RainfallOutletMonitoringLog> page = new Page <> ( dto.getPageNum () , dto.getPageSize () );
        LambdaQueryWrapper<RainfallOutletMonitoringLog>  wrapper = new LambdaQueryWrapper <> ();
        wrapper.eq(RainfallOutletMonitoringLog::getMonitoringId,entity.getId());
        if (!CollectionUtils.isEmpty( dto.getTimes () ) &&dto.getTimes().get(0)!=null) {
            wrapper .ge(RainfallOutletMonitoringLog::getMonitoringTime , dto.getTimes ().get ( 0 ) );
        }
        if (!CollectionUtils.isEmpty( dto.getTimes () ) &&dto.getTimes().get(1)!=null) {
            wrapper.le(RainfallOutletMonitoringLog::getMonitoringTime , dto.getTimes ().get ( 1 ));
        }
        wrapper.orderByDesc( RainfallOutletMonitoringLog::getMonitoringTime );
        Page<RainfallOutletMonitoringLog> wasteGasMonitoringLogs=rainfallOutletMonitoringLogService.page(
                page, wrapper
        );
        List<RainfallOutletExcelExportDTO> voList=wasteGasMonitoringLogs.getRecords().stream().map(i->{
            RainfallOutletExcelExportDTO wasteGasExcelExportDTO = new RainfallOutletExcelExportDTO ();
            BeanUtils.copyProperties ( i , wasteGasExcelExportDTO );
            wasteGasExcelExportDTO.setMonitoringTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(i.getMonitoringTime()));
            wasteGasExcelExportDTO.setStatus(MachineStatusEnums.getDesc(i.getStatus()));
//            wasteGasExcelExportDTO.setRainOutletValveStatus(ValveStatusEnums.getDesc(i.getRainOutletValveStatus()));
            if (wasteGasExcelExportDTO.getDeviceName().contains("雨排口")){
                wasteGasExcelExportDTO.setEmergencyPoolLevel(i.getRainOutletLevel());
                wasteGasExcelExportDTO.setEmergencyPoolValveStatus(i.getRainOutletValveStatus());
            }
            wasteGasExcelExportDTO.setEmergencyPoolValveStatus(ValveStatusEnums.getDesc(i.getEmergencyPoolValveStatus()));
            return wasteGasExcelExportDTO;
        }).toList();
        Page < RainfallOutletExcelExportDTO > voPage = new Page <> ();
        BeanUtils.copyProperties ( wasteGasMonitoringLogs , voPage , "records" );
        voPage.setRecords ( voList );
        vo.setDetails(voPage);
        vo.setStatus(MachineStatusEnums.getDesc(vo.getStatus()));
        return ResultVO.ok ( vo );
    }

    @Override
    public void export(RainfallOutletDetailDTO dto, HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 防止中文乱码
        String fileName = URLEncoder.encode("检测详情", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        RainfallOutletMonitoring entity = this.getById ( dto.getId() );
        LambdaQueryWrapper<RainfallOutletMonitoringLog>  wrapper = new LambdaQueryWrapper <> ();
        wrapper.eq(RainfallOutletMonitoringLog::getMonitoringId,entity.getId());
        if (!CollectionUtils.isEmpty( dto.getTimes () ) &&dto.getTimes().get(0)!=null) {
            wrapper .ge(RainfallOutletMonitoringLog::getMonitoringTime , dto.getTimes ().get ( 0 ) );
        }
        if (!CollectionUtils.isEmpty( dto.getTimes () ) &&dto.getTimes().get(1)!=null) {
            wrapper.le(RainfallOutletMonitoringLog::getMonitoringTime , dto.getTimes ().get ( 1 ));
        }
        wrapper.orderByDesc( RainfallOutletMonitoringLog::getMonitoringTime );

        List<RainfallOutletMonitoringLog> wasteGasMonitoringLogs=rainfallOutletMonitoringLogService.list(
                 wrapper
        );
        List<RainfallOutletExcelExportDTO> voList=wasteGasMonitoringLogs.stream().map(i->{
            RainfallOutletExcelExportDTO wasteGasExcelExportDTO = new RainfallOutletExcelExportDTO ();
            BeanUtils.copyProperties ( i , wasteGasExcelExportDTO );
            wasteGasExcelExportDTO.setMonitoringTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(i.getMonitoringTime()));
            wasteGasExcelExportDTO.setStatus(MachineStatusEnums.getDesc(i.getStatus()));
//            wasteGasExcelExportDTO.setRainOutletValveStatus(ValveStatusEnums.getDesc(i.getRainOutletValveStatus()));
            if (wasteGasExcelExportDTO.getDeviceName().contains("雨排口")){
                wasteGasExcelExportDTO.setEmergencyPoolLevel(i.getRainOutletLevel());
                wasteGasExcelExportDTO.setEmergencyPoolValveStatus(i.getRainOutletValveStatus());
            }
            wasteGasExcelExportDTO.setEmergencyPoolValveStatus(ValveStatusEnums.getDesc(i.getEmergencyPoolValveStatus()));
            return wasteGasExcelExportDTO;
        }).toList();
        EasyExcel.write(response.getOutputStream(), RainfallOutletExcelExportDTO.class)
                .sheet("用户信息")
                .doWrite(voList);
    }

    @Override
    public ResultVO operation(RainfallOutletOperationDTO rainfallOutletOperationDTO) {
        // 参数校验
        if (rainfallOutletOperationDTO == null || StringUtils.isBlank(rainfallOutletOperationDTO.getId())) {
            return ResultVO.fail("ID不能为空");
        }
        if (StringUtils.isBlank(rainfallOutletOperationDTO.getOperation())) {
            return ResultVO.fail("操作类型不能为空");
        }

        // 根据id查找RainfallOutletMonitoring实体
        RainfallOutletMonitoring entity = this.getById(rainfallOutletOperationDTO.getId());
        if (entity == null) {
            return ResultVO.fail("记录不存在");
        }

        // 检查设备是否已连接
        if (!hj212Server.isClientConnectedByMn(entity.getMnCode())) {
            return ResultVO.fail("设备未连接，无法发送指令");
        }

        try {
            if ("1".equals(rainfallOutletOperationDTO.getOperation())) {
                // 开阀操作
                return executeOpenValveOperation(entity);
            } else if ("0".equals(rainfallOutletOperationDTO.getOperation())) {
                // 关阀操作
                return executeCloseValveOperation(entity);
            } else {
                return ResultVO.fail("无效的操作类型");
            }
        } catch (Exception e) {
            log.error("执行阀门操作失败", e);
            return ResultVO.fail("操作失败：" + e.getMessage());
        }
    }

    /**
     * 执行开阀操作
     */
    private ResultVO executeOpenValveOperation(RainfallOutletMonitoring entity) {
        log.info("开始执行开阀操作 - MN: {}", entity.getMnCode());
        
        // 1. 发送远控开启指令
        if (StringUtils.isNotBlank(entity.getRemoteOpenCmd())) {
            boolean success = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getRemoteOpenCmd());
            if (!success) {
                return ResultVO.fail("远控开启指令发送失败");
            }
            log.info("远控开启指令发送成功 - MN: {}", entity.getMnCode());
        }

        // 2. 延迟3秒后发送开阀指令
        if (StringUtils.isNotBlank(entity.getValveOpenCmd())) {
            scheduledExecutorService.schedule(() -> {
                try {
                    boolean success = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getValveOpenCmd());
                    if (success) {
                        log.info("开阀指令发送成功 - MN: {}", entity.getMnCode());
                        
                        // 3. 延迟2分钟后发送开阀结束指令
                        if (StringUtils.isNotBlank(entity.getValveOpenEndCmd())) {
                            scheduledExecutorService.schedule(() -> {
                                try {
                                    boolean endSuccess = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getValveOpenEndCmd());
                                    if (endSuccess) {
                                        log.info("开阀结束指令发送成功 - MN: {}", entity.getMnCode());
                                    } else {
                                        log.error("开阀结束指令发送失败 - MN: {}", entity.getMnCode());
                                    }
                                } catch (Exception e) {
                                    log.error("发送开阀结束指令异常 - MN: {}", entity.getMnCode(), e);
                                }
                            }, 2, TimeUnit.MINUTES);
                        }
                    } else {
                        log.error("开阀指令发送失败 - MN: {}", entity.getMnCode());
                    }
                } catch (Exception e) {
                    log.error("发送开阀指令异常 - MN: {}", entity.getMnCode(), e);
                }
            }, 3, TimeUnit.SECONDS);
        }

        // 4. 延迟2分3秒后发送远控关闭指令
        if (StringUtils.isNotBlank(entity.getRemoteCloseCmd())) {
            scheduledExecutorService.schedule(() -> {
                try {
                    boolean success = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getRemoteCloseCmd());
                    if (success) {
                        log.info("远控关闭指令发送成功 - MN: {}", entity.getMnCode());
                    } else {
                        log.error("远控关闭指令发送失败 - MN: {}", entity.getMnCode());
                    }
                } catch (Exception e) {
                    log.error("发送远控关闭指令异常 - MN: {}", entity.getMnCode(), e);
                }
            }, 130, TimeUnit.SECONDS); // 2分3秒 = 123秒
        }

        return ResultVO.ok("开阀操作已启动");
    }

    /**
     * 执行关阀操作
     */
    private ResultVO executeCloseValveOperation(RainfallOutletMonitoring entity) {
        log.info("开始执行关阀操作 - MN: {}", entity.getMnCode());
        
        // 1. 发送远控开启指令
        if (StringUtils.isNotBlank(entity.getRemoteOpenCmd())) {
            boolean success = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getRemoteOpenCmd());
            if (!success) {
                return ResultVO.fail("远控开启指令发送失败");
            }
            log.info("远控开启指令发送成功 - MN: {}", entity.getMnCode());
        }

        // 2. 延迟3秒后发送关阀指令
        if (StringUtils.isNotBlank(entity.getValveCloseCmd())) {
            scheduledExecutorService.schedule(() -> {
                try {
                    boolean success = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getValveCloseCmd());
                    if (success) {
                        log.info("关阀指令发送成功 - MN: {}", entity.getMnCode());
                        
                        // 3. 延迟2分钟后发送关阀结束指令
                        if (StringUtils.isNotBlank(entity.getValveCloseEndCmd())) {
                            scheduledExecutorService.schedule(() -> {
                                try {
                                    boolean endSuccess = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getValveCloseEndCmd());
                                    if (endSuccess) {
                                        log.info("关阀结束指令发送成功 - MN: {}", entity.getMnCode());
                                    } else {
                                        log.error("关阀结束指令发送失败 - MN: {}", entity.getMnCode());
                                    }
                                } catch (Exception e) {
                                    log.error("发送关阀结束指令异常 - MN: {}", entity.getMnCode(), e);
                                }
                            }, 2, TimeUnit.MINUTES);
                        }
                    } else {
                        log.error("关阀指令发送失败 - MN: {}", entity.getMnCode());
                    }
                } catch (Exception e) {
                    log.error("发送关阀指令异常 - MN: {}", entity.getMnCode(), e);
                }
            }, 3, TimeUnit.SECONDS);
        }

        // 4. 延迟2分3秒后发送远控关闭指令
        if (StringUtils.isNotBlank(entity.getRemoteCloseCmd())) {
            scheduledExecutorService.schedule(() -> {
                try {
                    boolean success = hj212Server.sendMessageByMn(entity.getMnCode(), entity.getRemoteCloseCmd());
                    if (success) {
                        log.info("远控关闭指令发送成功 - MN: {}", entity.getMnCode());
                    } else {
                        log.error("远控关闭指令发送失败 - MN: {}", entity.getMnCode());
                    }
                } catch (Exception e) {
                    log.error("发送远控关闭指令异常 - MN: {}", entity.getMnCode(), e);
                }
            }, 130, TimeUnit.SECONDS); // 2分3秒 = 123秒
        }

        return ResultVO.ok("关阀操作已启动");
    }
}
